// Copyright (C) 2018-2025 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <memory>
#include <type_traits>

#include "openvino/core/attribute_visitor.hpp"
#include "openvino/core/except.hpp"
#include "openvino/core/node.hpp"
#include "openvino/core/node_vector.hpp"
#include "openvino/core/shape.hpp"
#include "openvino/core/type/element_type.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/op.hpp"

namespace ov::snippets::op {

/**
 * @interface Scalar
 * @brief Generated by Canonicalization for a scalar constant Shape() == {1}
 * @ingroup snippets
 */
class Scalar : public ov::op::v0::Constant {
public:
    OPENVINO_OP("Scalar", "SnippetsOpset", ov::op::v0::Constant);

    Scalar() = default;

    template <class T, class = std::enable_if_t<std::is_fundamental_v<T>>>
    Scalar(const element::Type& type, Shape shape, T value) : Constant(type, shape, value) {
        constructor_validate_and_infer_types();
    }
    explicit Scalar(const Constant& other) : Constant(other) {
        constructor_validate_and_infer_types();
    }
    Scalar(const Scalar& other) : Constant(other) {
        constructor_validate_and_infer_types();
    }
    Scalar& operator=(const Scalar&) = delete;

    template <class T, class = std::enable_if_t<std::is_fundamental_v<T>>>
    T get_value() const {
        const auto vec = cast_vector<T>();
        OPENVINO_ASSERT(vec.size() == 1, "Scalar must have a single value");
        return vec[0];
    }

    std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
    void validate_and_infer_types() override;
    bool visit_attributes(AttributeVisitor& visitor) override;

    bool has_evaluate() const override {
        return false;
    }
};

}  // namespace ov::snippets::op
